﻿/**
 * Router Beta AS3 Framework
 * @version 1.0
 * @since 2010
 */
package com.routerbeta.net
{
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.ProgressEvent;
	import flash.events.IOErrorEvent;
	import flash.net.URLRequest;
	
	/**
	 * Carregador de arquivos JPG, GIF, PNG e SWF.
	 * 
	 * @version 1.5
	 * @date 30/04/2010
	 * 
	 * @author Will Soares @ willsoares.com
	 * @since 10/02/2009
	 */
	public class FileLoader extends EventDispatcher
	{
		/** ID atribuído ao objeto. */
		public var id:int;
		
		/** Informa se o objeto deve propagar seus eventos com <code>bubbles</code>. */
		public var propagateEvents:Boolean = false;
		
		/** URL do arquivo sendo carregado. */
		public function get url():String
		{
			return _url;
		}
		private var _url:String;
		
		/** Arquivo carregado convertido para um <code>DisplayObject</code>. */
		public function get content():DisplayObject
		{
			if(loader != null && loader.content != null)
				return loader.content as DisplayObject;
			else
				return null;
		}
		
		/** Tipo de arquivo carregado. */
		public function get contentType():String
		{
			if(info != null)
				return info.contentType;
			else
				return null;
		}
		
		/** Bytes carregados até o momento. */
		public function get bytesLoaded():uint
		{
			if(info != null)
				return info.bytesLoaded;
			else
				return 0;
		}
		
		/** Tamanho do arquivo em Bytes. */
		public function get bytesTotal():uint
		{
			if(info != null)
				return info.bytesTotal;
			else
				return 0;
		}
		
		/** Razão entre a quantidade de Bytes carregados em relação ao tamanho do arquivo. */
		public function get loadRatio():Number
		{
			if(bytesTotal > 0)
				return bytesLoaded / bytesTotal;
			else
				return 0;
		}
		
		/** Informa se o objeto ainda está carregando. */
		public function get loading():Boolean
		{
			if(info != null)
				return info.hasEventListener("complete");
			else
				return false;
		}
		
		/** Informa se o arquivo foi carregado. */
		public function get loaded():Boolean
		{
			return !loading && loadRatio == 1;
		}
		/**
		 * @private
		 */
		private var loader:Loader;
		private function get info():LoaderInfo
		{
			return loader.contentLoaderInfo;
		}
		
		/**
		 * Carregador de arquivos JPG, GIF, PNG e SWF.
		 * @param	propagateEvents
		 */
		public function FileLoader(propagateEvents:Boolean = false):void
		{
			this.propagateEvents = propagateEvents;
		}
		
		/**
		 * Carrega arquivos JPG, GIF, PNG ou SWF.
		 * @param	url
		 */
		public function load(url:String):void
		{
			_url = url;
			
			unload();
			
			loader = new Loader();
			
			info.addEventListener("open", onOpen);
			info.addEventListener("init", onInit);
			info.addEventListener("progress", onProgress);
			info.addEventListener("complete", onComplete);
			info.addEventListener("ioError", onIoError);
			
			loader.load(new URLRequest(url));
		}
		
		/**
		 * Para carregamento e limpa o cache.
		 */
		public function unload():void
		{
			if (loader)
			{
				if(bytesTotal > 0 && loading)
					loader.close();
					
				loader.unload();
				removeListeners();
				
				loader = null;
			}
		}
		
		/**
		 * Remove listeners do objeto <code>Loader</code>.
		 */
		private function removeListeners():void
		{
			info.removeEventListener("open", onOpen);
			info.removeEventListener("init", onInit);
			info.removeEventListener("progress", onProgress);
			info.removeEventListener("complete", onComplete);
			info.removeEventListener("ioError", onIoError);
		}
		
		/**
		 * Gatilho para evento INIT.
		 * @param	e
		 */
		private function onOpen(e:Event):void
		{
			dispatchEvent(new Event(Event.INIT, propagateEvents, propagateEvents));
		}
		
		/**
		 * Gatilho para evento OPEN.
		 * @param	e
		 */
		private function onInit(e:Event):void {
			dispatchEvent(new Event(Event.OPEN, propagateEvents, propagateEvents));
		}
		
		/**
		 * Gatilho para evento PROGRESS.
		 * @param	e
		 */
		private function onProgress(e:ProgressEvent):void {
			dispatchEvent(new ProgressEvent(ProgressEvent.PROGRESS, propagateEvents, propagateEvents, bytesLoaded, bytesTotal));
		}
		
		/**
		 * Gatilho para evento COMPLETE.
		 * @param	e
		 */
		private function onComplete(e:Event):void {
			removeListeners();
			dispatchEvent(new Event(Event.COMPLETE, propagateEvents, propagateEvents));
		}
		
		/**
		 * Gatilho para evento IO_ERROR.
		 * @param	e
		 */
		private function onIoError(e:IOErrorEvent):void {
			trace(e.text)
			removeListeners();
			dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR, propagateEvents, propagateEvents, e.text));
		}
		
	}
	
}